package org.leafDomain.hbase.impl;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.log4j.Logger;
import org.leafDomain.hbase.HBase;

import java.io.IOException;
import java.util.List;
import java.util.Properties;

public class HBaseImpl implements HBase {

    private final Properties config;
    private Connection con;
    private Table hbaseTable;
    private static final Logger loggerHBase = Logger.getLogger(HBaseImpl.class);
    public HBaseImpl(Properties config) {
        this.config = config;
    }

    @Override
    public void init() throws Exception {
        con = getCon();
        loggerHBase.info("RDB 创建[ 连接 ]对象成功");
        hbaseTable = checkAndGetTable(con);
        loggerHBase.info("RDB 获取[ 数据表 ]对象成功");
    }
    @Override
    public void putBatch(List<Put> batch) throws IOException {
        hbaseTable.put(batch);
    }

    @Override
    public Properties config() {
        return config;
    }

    @Override
    public void close() {
        closeAll(hbaseTable, con);
    }


    @Override
    public void closeAll(AutoCloseable... acs) {
        HBase.super.closeAll(acs);
    }



    /**
     * 检查并获取配置文件信息
     * @return 配置信息
     */
    private String tableName() {
        return checkAndGetConfig("hbase.table.name");
    }
    private String zkUrl(){
        return checkAndGetConfig("hbase.zk");
    }

    /**
     * 创建一个HBase连接对象。
     *
     * @return Connection HBase连接对象。
     * @throws IOException 如果在创建连接过程中发生I/O错误。
     */
    private Connection getCon() throws IOException {
        // 创建一个HBase配置对象
        Configuration config = HBaseConfiguration.create();
        // 设置ZooKeeper的地址
        config.set("hbase.zookeeper.quorum", zkUrl());
        // 使用配置对象创建HBase连接并返回
        return ConnectionFactory.createConnection(config);
    }

    /**
     * 检查HBase中是否存在指定名称的表，如果存在则返回该表的Table对象。
     *
     * @param con HBase连接对象。
     * @return Table 存在且可访问的HBase表对象。
     * @throws IOException 如果表不存在或发生I/O错误。
     */
    private Table checkAndGetTable(Connection con) throws IOException {
        // 获取HBase的Admin对象，用于执行DDL操作
        final Admin admin = con.getAdmin();
        // 将表名转换为TableName对象
        TableName tableName = TableName.valueOf(tableName());
        // 检查表是否存在
        if (!admin.tableExists(tableName)) {
            // 如果表不存在，则抛出IOException异常
            throw new IOException("HBase表不存在异常: " + tableName);
        }
        // 如果表存在，则返回该表的Table对象
        return con.getTable(tableName);
    }
}
